home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 June / Macworld (1999-06).dmg / Shareware World / Info / For Developers / MacZoop2.0.sea / MacZoop2.0 / Required Classes / ZEventHandler.cpp < prev    next >
Text File  |  1999-02-23  |  22KB  |  851 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"             
  5. *
  6. *
  7. *
  8. *            ZEventHandler.cpp        -- the event handler object
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21. #include    "ZEventHandler.h"
  22. #include    "MacZoop.h"
  23. #include    "ProjectSettings.h"
  24. #include    "ZWindow.h"
  25. #include    "ZCommander.h"
  26. #include    "ZDialog.h"
  27.  
  28. #include    <LowMem.h>
  29. #include    <MixedMode.h>
  30.  
  31. // gSleep is the sleep period passed to WaitNextEvent
  32.  
  33. short            gSleep = kFrontSleep;
  34.  
  35. // gCurHandler is the current ZCommander object that wants to handle commands. This will
  36. // usually be the active window or the application
  37.  
  38. ZCommander*        gCurHandler = NULL;
  39.  
  40. // prototype of handler function for apple-events- sends them up the command chain.
  41.  
  42. static pascal OSErr        ZAEHandler ( AppleEvent* aeEvt, AppleEvent* reply, long refCon );
  43.  
  44. // global UPP to same
  45.  
  46. AEEventHandlerUPP        gAEUPP  = NewAEEventHandlerProc( ZAEHandler );
  47.  
  48.  
  49. /*-------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  50.  
  51. ZEventHandler::ZEventHandler()
  52. {
  53.     clicks = 0;
  54.     inBackground = FALSE;
  55.     epPPCYokeDown = 0;
  56.     
  57.     gCurHandler = gApplication;
  58. }
  59.  
  60.  
  61. /*--------------------------***  ESTABLISHCURRENTHANDLER  ***---------------------------*/
  62. /*    
  63.  
  64. set up the value of <gCurHandler> by querying the active window
  65. ----------------------------------------------------------------------------------------*/
  66.  
  67. void    ZEventHandler::EstablishCurrentHandler()
  68. {
  69.     ZWindow*    zw = gWindowManager->GetTopWindow();
  70.     
  71.     // we only dispatch Idle if the window is active.
  72.     
  73.     if ( zw && zw->IsActive())
  74.         gCurHandler = zw->GetHandler();    // this method returns the handler within the window
  75.                                         // or the window itself.
  76.     else
  77.         gCurHandler = gApplication;
  78. }
  79.  
  80.  
  81. /*---------------------------------***  GETANEVENT  ***---------------------------------*/
  82. /*    
  83.  
  84. gets the next event off the queue. If it's a null event, give idle time
  85.  
  86. ----------------------------------------------------------------------------------------*/
  87.  
  88. void    ZEventHandler::GetAnEvent( EventRecord* theEvent, const short mask )
  89. {
  90.     // gets an event from the event queue and sets "theEvent" to it. On the PowerPC, WNE is
  91.     // an emulated trap and performance can be enhanced by calling it much less frequently
  92.     // than once per loop. If we're running on PowerPC, we use the "epPPCYokeDown" variable
  93.     // to count our main loops. If we do not call WNE, we pretend that the event is a NULL
  94.     // event. The default is 32 loops per event.
  95.     
  96. #if GENERATINGPOWERPC
  97.  
  98.     Boolean        isIdle;
  99.     
  100.     // for some events, we want to immediately handle them. However, calling EventAvail
  101.     // offsets some of the advantage of doing this yokedown anyway, so we check this
  102.     // every four calls to try and keep the speed improvement as good as possible. As always
  103.     // this is a tradeoff between good responsiveness and fast execution.
  104.     
  105.     if (( epPPCYokeDown % 4 ) == 0 )
  106.     {
  107.         if ( EventAvail( mDownMask + keyDownMask + updateMask, theEvent ))
  108.             epPPCYokeDown = 0;
  109.     }
  110.     
  111.     if ( epPPCYokeDown <= 0 )
  112.     {
  113.         isIdle = ! WaitNextEvent( mask, theEvent, gSleep, NULL );
  114.         epPPCYokeDown = kPowerPCWNEYokeDown;
  115.     }
  116.     else
  117.     {
  118.         theEvent->what = nullEvent;
  119.         theEvent->message = 0;
  120.         theEvent->when = TickCount();
  121.         
  122.         GetMouse( &theEvent->where );
  123.         LocalToGlobal( &theEvent->where );
  124.         
  125.         theEvent->modifiers = GetModifiers();
  126.         
  127.         // decrement loop counter
  128.         
  129.         isIdle = TRUE;
  130.         epPPCYokeDown--;
  131.     }
  132.     
  133.     // if main screen has changed depth, send a message to tell any interested party
  134.     // about it.
  135.     
  136.     short    sd = GetMainScreenDepth();
  137.     
  138.     if ( sd != gApplication->msDepth )
  139.     {
  140.         gApplication->msDepth = sd;
  141.         gApplication->SendMessage( msgMainScreenDepthChanged, &sd );
  142.     }
  143.     
  144.     if ( isIdle )
  145.         PassIdle();
  146.  
  147. #else
  148.  
  149.     if (! WaitNextEvent( mask, theEvent, gSleep, NULL ))
  150.         PassIdle();
  151.  
  152. #endif
  153.     
  154.     gApplication->HandleMBarHiding( theEvent->where );
  155.         
  156.     // dispatch the cursor to the current window, so it's shape can be set.
  157.     
  158.     if ( !inBackground )
  159.     {
  160.         // if control key down, show contextual menu cursor and do NOT dispatch to window
  161.         
  162.         if ( gMacInfo.hasContextualMenus && ( theEvent->modifiers & controlKey ) == controlKey )
  163.             SetCursorShape( CONTEXT_MENU_CURSOR );
  164.         else
  165.         {
  166.             ZWindow*    aZW = gWindowManager->LocateWindow( theEvent->where );
  167.             
  168.             if ( aZW )
  169.             {
  170.                 WindowPtr w = aZW->GetMacWindow();
  171.             
  172.                 // check to see that the window is not "windowshaded"- if
  173.                 // it is, don't dispatch the cursor. If the window is shaded,
  174.                 // its contRgn will be empty.
  175.                 
  176.                 if (! EmptyRgn( ((WindowPeek) w)->contRgn ))
  177.                 {
  178.                     if ( aZW )
  179.                     {
  180.                         Point        mouse;
  181.                         GrafPtr        savePort;
  182.                         
  183.                         mouse = theEvent->where;
  184.                         
  185.                         GetPort( &savePort );
  186.                         SetPort( w );
  187.                         GlobalToLocal( &mouse );
  188.                         SetPort( savePort );
  189.                         
  190.                         // handle balloon help for the window. We only need to consider the frontmost
  191.                         // window or floaters since the system displays balloons for other windows
  192.                         
  193.                         if ( aZW->Floats() ||
  194.                              aZW == gApplication->GetFrontWindow())
  195.                             DoBalloons( aZW, theEvent->where );
  196.  
  197.                         // if the point is inside the window, dispatch to the window,
  198.                         // otherwise reset the cursor to an arrow. If the window is not the top
  199.                         // window, the cursor is not dispatched, but reset, unless the window is
  200.                         // a floater, in which case we do dispatch it if there not a modal dialog
  201.                         // in front of it. The result is correct for what the user expects.
  202.                         
  203.                         if     ( PtInRect( mouse, &w->portRect ) &&
  204.                             ( aZW == gApplication->GetFrontWindow() ||
  205.                             ( aZW->Floats() && ! gWindowManager->IsDialog( gApplication->GetFrontWindow()))))
  206.                             aZW->AdjustCursor( mouse, theEvent->modifiers );
  207.                         else
  208.                             gApplication->MouseNotInAnyWindow( theEvent->where );
  209.                     }
  210.                 }
  211.                 else
  212.                     gApplication->MouseNotInAnyWindow( theEvent->where );
  213.             }
  214.             else
  215.                 gApplication->MouseNotInAnyWindow( theEvent->where );
  216.         }
  217.     }
  218. }
  219.  
  220.  
  221. /*-----------------------------***  DISPATCHANEVENT  ***--------------------------------*/
  222. /*    
  223.  
  224. determine what sort of event it is and call the relevant handler method.
  225.  
  226. ----------------------------------------------------------------------------------------*/
  227.  
  228. void    ZEventHandler::DispatchAnEvent( EventRecord* theEvent )
  229. {
  230.     // dispatches the event according to its type, etc
  231.     
  232.     Boolean        isAutoKey = FALSE;
  233.     char         theKey;
  234.     
  235.     FailNILParam( theEvent );
  236.     lastEvent = *theEvent;
  237.             
  238.     // set up gCurHandler
  239.     
  240.     EstablishCurrentHandler();
  241.  
  242.     // dispatch the event to the handler
  243.     
  244.     switch ( theEvent->what )
  245.     {
  246.         case mouseDown:
  247.             HandleMouseEvent( *theEvent );
  248.             break;
  249.         
  250.         case activateEvt:
  251.             
  252.             // following defined in Project Settings.h
  253.             
  254.             #if _ACTIVATE_EVENTS_ARE_REAL
  255.             HandleWindowActivate(    (WindowPtr) theEvent->message,
  256.                                     (theEvent->modifiers & activeFlag) );
  257.             #endif
  258.             break;
  259.         
  260.         case autoKey:
  261.             isAutoKey = TRUE;
  262.         
  263.         case keyDown:
  264.             theKey = theEvent->message & charCodeMask;
  265.             
  266.             HandleKeyEvent( theKey, isAutoKey, theEvent->modifiers );
  267.             break;
  268.         
  269.         case updateEvt:
  270.             HandleWindowUpdate((WindowPtr) theEvent->message );
  271.             break;
  272.         
  273.         case diskEvt:
  274.         {
  275.             Point dPt = {100,100};
  276.             
  277.             if( HiWord( theEvent->message ) != 0)
  278.                 DIBadMount( dPt, theEvent->message );
  279.             break;
  280.         }
  281.         
  282.         case kHighLevelEvent:
  283.             HandleHLEvent( *theEvent );
  284.             break;
  285.         
  286.         case osEvt:
  287.             HandleOSEvent( *theEvent );
  288.             break;
  289.     }
  290. }
  291.  
  292.  
  293. /*------------------------------***  HANDLEKEYEVENT  ***--------------------------------*/
  294. /*    
  295.  
  296. process keystrokes. Command-Key sequences are passed to the menu handler
  297. ----------------------------------------------------------------------------------------*/
  298.  
  299. void    ZEventHandler::HandleKeyEvent( const char theKey, const Boolean isAutoKey, short modifiers )
  300. {
  301.     long mSelect;
  302.     
  303.     if ( modifiers & cmdKey )
  304.     {
  305.         // if this is a command-key combination, translate this to a
  306.         // menu command as if it were picked from the menu.
  307.         
  308.         if (! isAutoKey)
  309.         {
  310.             gMenuBar->DimMenus();
  311.             
  312.             // ask the command chain to reenable the relevant menu items
  313.             
  314.             if ( gCurHandler )
  315.                 gCurHandler->UpdateMenus();
  316.                 
  317.             // check for a keyboard shortcut. If there is one, dispatch it,
  318.             // otherwise pass the key to the command chain for processing
  319.                 
  320.             mSelect = MenuKey( theKey );
  321.             
  322.             if ( HiWord( mSelect ) != 0 )
  323.             {
  324.                 gMenuBar->DispatchCommand( mSelect );
  325.                 return;
  326.             }
  327.         }    
  328.     }
  329.     
  330.     // add in autokey flag to modifiers, for the benefit of Type() methods...
  331.     
  332.     if ( isAutoKey )
  333.         modifiers |= FromAutoKeyEvent;
  334.  
  335.     // the user is typing- send the characters to the current commander
  336.     
  337.     if ( gCurHandler )
  338.         gCurHandler->Type( theKey, modifiers );
  339. }
  340.  
  341.  
  342. /*-------------------------------***  COUNTCLICKS  ***----------------------------------*/
  343. /*    
  344.  
  345. count up the number of rapid mouse-clicks to detect double-clicks, etc.
  346.  
  347. ----------------------------------------------------------------------------------------*/
  348.  
  349. void    ZEventHandler::CountClicks( const WindowPtr target, const long clickTicks, const Point globalMouse )
  350. {
  351.     static    WindowPtr     prevTarget = NULL;
  352.     static    long        lastClickTicks = 0;
  353.     static    Point        lastClick = {0,0};
  354.     
  355.     GrafPtr    savePort;
  356.     Point    gMouse;
  357.     
  358.     gMouse = globalMouse;
  359.     
  360.     GetPort( &savePort );
  361.     SetPort( target );
  362.     GlobalToLocal( &gMouse );
  363.     
  364.     if (target == prevTarget)
  365.     {
  366.         // the target window is the same as the last click, is the click
  367.         // within the double-click period set by the user?
  368.         
  369.         if ( clickTicks < lastClickTicks + GetDblTime())
  370.         {
  371.             // yes, the click is in time. Finally, we ask the window
  372.             // whether we should consider the click as being in the same place.    
  373.             
  374.             ZWindow*    zW = GetZWindow( target );
  375.             
  376.             if ( zW && zW->ClickInSamePlace( lastClick, gMouse ))
  377.                 clicks++;
  378.             else
  379.                 clicks = 1;
  380.         }
  381.         else
  382.             clicks = 1;
  383.     }
  384.     else
  385.         clicks = 1;
  386.     
  387.     // store the click point, target and click time for the next time
  388.             
  389.     lastClick = gMouse;
  390.     prevTarget = target;
  391.     lastClickTicks = clickTicks;
  392.  
  393.     SetPort( savePort );
  394. }
  395.  
  396.  
  397. /*---------------------------***  HANDLEMOUSEEVENT  ***---------------------------------*/
  398. /*    
  399.  
  400. handle mouse button clicks. This finds the target window or other part of the screen
  401.  
  402. ----------------------------------------------------------------------------------------*/
  403.  
  404. void    ZEventHandler::HandleMouseEvent( const EventRecord& theEvent )
  405. {
  406.     WindowPtr        targetWindow;
  407.     short            partCode;
  408.     long            mSelect;
  409.     Point            mousePt;
  410.     ZWindow*        zappWindow;
  411.     
  412.     // find out what part of the screen the mouse was clicked on
  413.     
  414.     partCode = FindWindow( theEvent.where, &targetWindow );
  415.     
  416.     // if it was any sort of window, get the ZWindow object associated with it, if any.
  417.     
  418.     if ( targetWindow )
  419.         zappWindow = GetZWindow( targetWindow );
  420.     
  421.     switch (partCode)
  422.     {    
  423.         case inDesk:
  424.             SysBeep( 1 );
  425.             break;
  426.         
  427.         case inMenuBar:
  428.             // the user clicked the menubar.
  429.  
  430.             gMenuBar->ClickMenuBar( theEvent.where );
  431.             break;
  432.         
  433.         case inSysWindow:
  434.             SystemClick( &theEvent, targetWindow );    // system will handle it (DA window)
  435.             break;
  436.         
  437.         case inContent:
  438.             if ( targetWindow )                        // the user clicked in a window
  439.             {
  440.                 // if control key down, do a contextual menu pop-up instead
  441.                 
  442.                 if ( theEvent.modifiers & controlKey )
  443.                 {
  444.                     zappWindow->ContextualMenuClick( theEvent.where );
  445.                 }
  446.                 else
  447.                 {
  448.                     // if there's a modal dialog up, clicks in other windows result in a beep.
  449.                     
  450.                     ZWindow*    aZW = gApplication->GetFrontWindow();
  451.                     ZDialog*    aZD;
  452.                     
  453.                     if ( aZW )
  454.                         aZD = dynamic_cast<ZDialog*> ( aZW );
  455.                     else
  456.                         aZD = NULL;
  457.                         
  458.                     Boolean        dialogUp = ( aZD && aZD->IsModal());
  459.                     
  460.                     CountClicks( targetWindow, theEvent.when, theEvent.where );    // double click?
  461.                     
  462.                     // if the window is top window or top floater, pass the click to the window.
  463.                     
  464.                     if( zappWindow &&
  465.                         (zappWindow == gApplication->GetFrontWindow() ||
  466.                         (zappWindow == gWindowManager->GetTopFloater() && ! dialogUp )))
  467.                     {
  468.                         // if the window is already active, pass the click to the window object
  469.                         // in its local coordinate system.
  470.                         
  471.                         mousePt = theEvent.where;
  472.                         
  473.                         zappWindow->Focus();
  474.                         GlobalToLocal( &mousePt );
  475.                         zappWindow->Click( mousePt, theEvent.modifiers );    
  476.                     }
  477.                     else
  478.                     {
  479.                         // if the window wasn't active, make it active. If there is a modal dialog in
  480.                         // front, then this action is not permitted.
  481.                         
  482.                         if ( dialogUp )
  483.                         {
  484.                             SysBeep( 1 );
  485.                             break;
  486.                         }
  487.                         // otherwise, process the click    
  488.  
  489.                         if ( zappWindow )
  490.                         {
  491.                             // make this window the active one
  492.                             
  493.                             zappWindow->Select();
  494.                             
  495.                             // if the window is a floater, ask it to process the click as well- 
  496.                             // floaters process "front" clicks even when they were not initially
  497.                             // active, since floaters are all 'peers' of one another.
  498.                         
  499.                             if ( zappWindow->Floats())
  500.                             {
  501.                                 mousePt = theEvent.where;
  502.                                 
  503.                                 zappWindow->Focus();
  504.                                 GlobalToLocal( &mousePt );
  505.                                 zappWindow->Click( mousePt, theEvent.modifiers );
  506.                             }
  507.                         }
  508.                     }
  509.                 }
  510.             }
  511.             break;
  512.         
  513.         case inDrag:
  514.         {
  515.             // the user wants to drag the window. Only permit this if no
  516.             // modal dialog is in front of it, or the command key is down.
  517.             
  518.             ZDialog*    aZD = dynamic_cast<ZDialog*>( gApplication->GetFrontWindow());
  519.             
  520.             if ( aZD &&
  521.                  aZD->IsModal() &&
  522.                  (targetWindow != aZD->GetMacWindow()) &&
  523.                  ! (theEvent.modifiers & cmdKey))
  524.             {
  525.                 SysBeep( 1 );
  526.                 break;
  527.             }
  528.             ZWindow*    zw = GetZWindow( targetWindow );
  529.             gWindowManager->DragWindowOutline( zw, theEvent.where, theEvent.modifiers );
  530.             
  531.             break;
  532.         }
  533.         
  534.         case inGrow:
  535.         {
  536.             // the user wants to resize the window
  537.             
  538.             Rect szRect;
  539.             
  540.             if ( zappWindow )
  541.             {
  542.                 zappWindow->GetSizeRect( &szRect );
  543.                 
  544.                 szRect.right++;
  545.                 szRect.bottom++;
  546.                 
  547.                 mSelect = GrowWindow( targetWindow, theEvent.where, &szRect );
  548.             
  549.                 if ( mSelect )
  550.                 {
  551.                     // if the command key was down, then we are attempting to override the
  552.                     // current settings for sizerect. Thus we need to change the size rect
  553.                     // to the desired size first:
  554.                     
  555.                     if ( theEvent.modifiers & cmdKey )
  556.                     {
  557.                         szRect.right = MAX( LoWord( mSelect ), szRect.right - 1 );
  558.                         szRect.bottom = MAX( HiWord( mSelect ), szRect.bottom - 1 );
  559.                         
  560.                         zappWindow->SetSizeRect( szRect );
  561.                     }
  562.                     
  563.                     zappWindow->SetSize( LoWord( mSelect ), HiWord( mSelect ));
  564.                 }
  565.             }
  566.             break;
  567.         }
  568.         
  569.         case inGoAway:
  570.             if ( TrackGoAway( targetWindow, theEvent.where ))
  571.             {
  572.                 // if the user clicks in the go-away box, the window will be closed. If the
  573.                 // option key is down, we close all of the windows.
  574.                 
  575.                 if ( theEvent.modifiers & optionKey )
  576.                     gApplication->CloseAll( zappWindow->Floats());
  577.                 else
  578.                 {
  579.                     if ( zappWindow )
  580.                         zappWindow->Close( gApplication->GetPhase());
  581.                 }
  582.             }
  583.             break;
  584.         
  585.         case inZoomIn:
  586.         case inZoomOut:
  587.             if( TrackBox( targetWindow, theEvent.where, partCode ))
  588.             {
  589.                 // if the user clicked in the zoom box, the window will be zoomed
  590.                 
  591.                 if( zappWindow )
  592.                     zappWindow->Zoom( partCode );
  593.             }
  594.             break;
  595.     }
  596. }
  597.  
  598.  
  599. /*---------------------------***  HANDLEWINDOWUPDATE  ***-------------------------------*/
  600. /*    
  601.  
  602. to handle an update event, call the window object's update method.
  603.  
  604. ----------------------------------------------------------------------------------------*/
  605.  
  606. void    ZEventHandler::HandleWindowUpdate( const WindowPtr theWindow )
  607. {
  608.     ZWindow*        zappWindow = NULL;
  609.     Boolean            memState;
  610.     
  611.     if ( theWindow )
  612.         zappWindow = GetZWindow( theWindow );
  613.     
  614.     memState = gApplication->MemoryCrisis();
  615.     
  616.     if ( zappWindow )
  617.         zappWindow->PerformUpdate();
  618.         
  619.     // if the draw resulted in a memory shortage, suppress the warning, since
  620.     // that will trigger further updates, etc.
  621.         
  622.     if ( gApplication->MemoryCrisis() != memState )
  623.         gApplication->userHasSeenAlert = TRUE;
  624. }
  625.  
  626.  
  627.  
  628. /*---------------------------------***  PASSIDLE  ***-----------------------------------*/
  629. /*    
  630.  
  631. send the idle command to the current handler, and pass it up the chain
  632.  
  633. ----------------------------------------------------------------------------------------*/
  634.  
  635.  
  636. void    ZEventHandler::PassIdle()
  637. {
  638.     // called repeatedly for null events. This passes idle messages to the current commander
  639.     
  640.     EstablishCurrentHandler();
  641.  
  642.     if ( gCurHandler )
  643.         gCurHandler->Idle();
  644.         
  645.     // floaters may want idle time too, though they are not part of the command chain. We
  646.     // ask the window manager to give them time:
  647.     
  648.     gWindowManager->FloatIdle();
  649. }
  650.  
  651.  
  652.  
  653. /*--------------------------***  HANDLEWINDOWACTIVATE  ***------------------------------*/
  654. /*    
  655.  
  656. calls activate/deactivate for window
  657. ----------------------------------------------------------------------------------------*/
  658.  
  659. void    ZEventHandler::HandleWindowActivate( const WindowPtr theWindow, const Boolean state )
  660. {
  661.     // handles the activate and deactivate events. This calls the window object with
  662.     // the activate messages, and also sets up gCurHandler.
  663.  
  664.     ZWindow*        zw = NULL;
  665.     
  666.     if ( theWindow )
  667.         zw = GetZWindow( theWindow );
  668.     
  669.     if ( zw )
  670.     {
  671.         zw->Focus();
  672.         if ( state )
  673.             zw->Activate();
  674.         else
  675.             zw->Deactivate();
  676.     }
  677. }
  678.  
  679.  
  680. /*------------------------------***  HANDLEOSEVENT  ***---------------------------------*/
  681. /*    
  682.  
  683. handle the suspend and resume events sent by MultiFinder/System 7
  684. ----------------------------------------------------------------------------------------*/
  685.  
  686. void    ZEventHandler::HandleOSEvent( const EventRecord& theEvent )
  687. {
  688.     if ((( theEvent.message & 0xFF000000 ) >> 24 ) == suspendResumeMessage )
  689.     {
  690.         if ( theEvent.message & resumeFlag )
  691.         {
  692.             inBackground = FALSE;
  693.             gSleep = kFrontSleep;
  694.             
  695.             if ( theEvent.message & convertClipboardFlag )    
  696.                 gClipboard->ConvertToPrivate();
  697.                 
  698.             gCurHandler->DoResume();
  699.                 
  700.             ResumeCursorAnimation();
  701.         }
  702.         else
  703.         {
  704.             inBackground = TRUE;
  705.             gSleep = kBackSleep;
  706.             gMenuBar->ShowHideMenuBar( MBAR_SHOW );
  707.             gClipboard->ConvertFromPrivate();
  708.             
  709.             gCurHandler->DoSuspend();
  710.             
  711.             PauseCursorAnimation( 0 );
  712.         }
  713.         
  714.         SetCursorShape( ARROW_CURSOR );    
  715.     }
  716. }
  717.  
  718.  
  719. /*------------------------------***  HANDLEHLEVENT  ***---------------------------------*/
  720. /*    
  721.  
  722. handle the high level events sent by AOCE, Applescript, et al.
  723. ----------------------------------------------------------------------------------------*/
  724.  
  725. void    ZEventHandler::HandleHLEvent( const EventRecord& theEvent)
  726. {
  727.     // handles high level events such as applescript events, etc.
  728.     
  729.     if ( theEvent.message == typeAppleEvent )
  730.         FailOSErr( AEProcessAppleEvent( &theEvent ));
  731.     else
  732.         gApplication->ProcessHLEvent( theEvent );
  733. }
  734.  
  735.  
  736. /*-----------------------***  INSTALLAPPLESCRIPTHANDLERS  ***---------------------------*/
  737. /*    
  738.  
  739. install the handler vectors needed to field applescript events. BY default this installs
  740. the four required events. You can override this to install more, or call the method
  741. below as needed.
  742. ----------------------------------------------------------------------------------------*/
  743.  
  744. void    ZEventHandler::InstallApplescriptHandlers()
  745. {
  746.     InstallAppleEventHandler( kCoreEventClass, kAEOpenApplication );
  747.     InstallAppleEventHandler( kCoreEventClass, kAEOpenDocuments );
  748.     InstallAppleEventHandler( kCoreEventClass, kAEPrintDocuments );
  749.     InstallAppleEventHandler( kCoreEventClass, kAEQuitApplication );
  750.     
  751.     // MacOS 8 has a new core apple event for reopening the application...
  752.     
  753.     if ( gMacInfo.systemVersion >= 0x0800 )
  754.         InstallAppleEventHandler( kCoreEventClass, kAEReopenApplication );
  755. }
  756.  
  757.  
  758. /*------------------------***  INSTALLAPPLEEVENTHANDLER  ***----------------------------*/
  759. /*    
  760.  
  761. install the handler vector needed to field all applescript events. Call this once for
  762. each event class and ID you wish to process. Apple Events will be unpacked by the global
  763. vector proc and sent up the command chain. You can intercept them there and process them
  764. as needed.
  765. ----------------------------------------------------------------------------------------*/
  766.  
  767. void    ZEventHandler::InstallAppleEventHandler( const AEEventClass pClass, const AEEventID pID )
  768. {
  769.     // installs the AppleEvent hook for the given apple event
  770.     
  771.     if ( gMacInfo.hasAppleEvents )
  772.         FailOSErr( AEInstallEventHandler( pClass, pID, gAEUPP, (long) gApplication, FALSE ));
  773. }
  774.  
  775.  
  776.  
  777. /*-------------------------------***  DOBALLOONS  ***-----------------------------------*/
  778. /*    
  779.  
  780. display balloons as mouse tracks over windows, etc.
  781. ----------------------------------------------------------------------------------------*/
  782.  
  783. void    ZEventHandler::DoBalloons( ZWindow* aWindow, const Point globMouse )
  784. {
  785.     HMMessageRecord        hm;
  786.     Rect                br;
  787.     Point                tip, lm;
  788.     
  789.     if ( ! HMIsBalloon() && HMGetBalloons())
  790.     {
  791.         lm = globMouse;
  792.         
  793.         aWindow->Focus();
  794.         GlobalToLocal( &lm );
  795.  
  796.         if ( aWindow->GetBalloonHelp( lm, &br, &tip, &hm ))
  797.         {
  798.             if ( PtInRect( lm, &br ))
  799.                 aWindow->ShowBalloonHelp( &br, tip, &hm );
  800.         }
  801.         else
  802.             HMRemoveBalloon();
  803.     }
  804. }
  805.  
  806.  
  807. #pragma mark -
  808. /*---------------------------------*********************---------------------------------*/
  809.  
  810.  
  811. static pascal OSErr            ZAEHandler( AppleEvent* aeEvt, AppleEvent* reply, long refCon )
  812. {
  813.     // this is the global vector proc that is called for every apple event. This determines the
  814.     // event class and ID, then sends that info, plus the event, up the command chain, where,
  815.     // presumably, it will be handled.
  816.  
  817.     AEEventClass    pClass;
  818.     AEEventID        pID;
  819.     DescType        returnedType;
  820.     long            returnedSize;
  821.     OSErr            theErr = noErr;
  822.     
  823.     try
  824.     {
  825.         // determine the AE class and ID (this is laborious, so it's done here once and passed on)
  826.     
  827.         FailOSErr( AEGetAttributePtr(     aeEvt, keyEventClassAttr,
  828.                                          typeType, &returnedType,
  829.                                          &pClass, sizeof( AEEventClass ), &returnedSize ));
  830.  
  831.         FailOSErr( AEGetAttributePtr(     aeEvt, keyEventIDAttr,
  832.                                          typeType, &returnedType,
  833.                                          &pID, sizeof( AEEventID ), &returnedSize ));
  834.  
  835.         if ( gCurHandler )
  836.         {
  837.             gCurHandler->HandleAppleEvent( pClass, pID, aeEvt, reply );
  838.             theErr = noErr;
  839.         }
  840.         else
  841.             theErr = errAEEventNotHandled;
  842.     }
  843.     catch( OSErr err )
  844.     {
  845.         theErr = err;
  846.     }
  847.     
  848.     return theErr;
  849. }            
  850.  
  851.